//
//  tablet_instrument_view.m
//  sbrush
//
//  Created by Phillip Popp on 4/30/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "tablet_instrument_view.h"

/* TODO: sometimes this view doesn't get all mouse messages when other views 
 * have taken over.
 * consider [NSEvent addLocalMonitorForEventsMatchingMask:handler:]
 */

using namespace sbrush;

@implementation TabletInstrumentView

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        instrument = new Instrument();
		instrumentState = new InstrumentState();
		instrumentState->resize(2, 0, 6, 0);
		[self setAutoresizesSubviews:YES];
		[self setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
		_screenWidth = 1.0f;
		_screenHeight = 1.0f;
		_tabletXScale = 1.0f;
		_tabletYScale = 1.0f;
		_tabletZScale = 1.0f;
		_tabletPScale = 1.0f;
		_tabletTiltXScale = 1.0f;
		_tabletTiltYScale = 1.0f;
    }
    return self;
}

- (void)dealloc {
	delete instrument;
	delete instrumentState;
	[super dealloc];
}

- (void)viewDidMoveToWindow {
	[[self window] setAcceptsMouseMovedEvents:YES];
	[[self window] makeFirstResponder:self];
	[self setFrame:[[self superview] bounds]];
	[self needsDisplay];
	NSRect frame = [[[self window] screen] frame];
	_screenWidth = frame.size.width;
	_screenHeight = frame.size.height;
}

- (void)viewWillMoveToWindow:(NSWindow *)newWindow {
	[[self window] setAcceptsMouseMovedEvents:NO];
}

- (sbrush::Instrument*) instrument {
	return instrument;
}

- (void) zeroInstrumentState {
	for (size_t i = 0; i < instrumentState->boolSize(); i++) {
		instrumentState->bools()[i] = false;
	}
	for (size_t i = 0; i < instrumentState->intSize(); i++) {
		instrumentState->ints()[i] = 0;
	}
	for (size_t i = 0; i < instrumentState->floatSize(); i++) {
		instrumentState->floats()[i] = 0.0f;
	}
	for (size_t i = 0; i < instrumentState->doubleSize(); i++) {
		instrumentState->doubles()[i] = 0.0;
	}
}

- (BOOL) acceptsFirstResponder {
	return YES;
}

- (BOOL)becomeFirstResponder {
	return YES;
}

- (void)mouseDown:(NSEvent *)theEvent {
	[self handleMouseEvent:theEvent];
}

- (void)mouseDragged:(NSEvent *)theEvent {
	[self handleMouseEvent:theEvent];
}

- (void)mouseMoved:(NSEvent *)theEvent {
	[self handleMouseEvent:theEvent];
}

- (void)tabletPoint:(NSEvent *)theEvent {
	[self handleTabletEvent:theEvent];
}

- (void)tabletProximity:(NSEvent *)theEvent {
	[self zeroInstrumentState];
	instrumentState->bools()[0] = [theEvent isEnteringProximity];
	instrumentState->bools()[1] = !(instrumentState->bools()[0]);
	instrument->setState(*instrumentState);
}

- (void) handleMouseEvent:(NSEvent*)event {
	short subtype = [event subtype];
	if (subtype == NSTabletPointEventSubtype) {
		[self handleTabletEvent:event];
	}
	else if (subtype == NSTabletProximityEventSubtype) {
		[self tabletProximity:event];
	}
	else {
		[self zeroInstrumentState];
		NSPoint mousePoint = [NSEvent mouseLocation];
		instrumentState->floats()[0] = mousePoint.x / _screenWidth;
		instrumentState->floats()[1] = mousePoint.y / _screenHeight;
		instrument->setState(*instrumentState);
	}
}



- (void) handleTabletEvent:(NSEvent*)event {
	NSInteger absX, absY, absZ;
	NSPoint tilt;
	float pressure;
	absX = [event absoluteX];
	absY = [event absoluteY];
	absZ = [event absoluteZ];
	tilt = [event tilt];
	pressure = [event pressure];

	[self zeroInstrumentState];
	instrumentState->floats()[0] = (float)absX / _tabletXScale;
	instrumentState->floats()[1] = (float)absY / _tabletYScale;
	instrumentState->floats()[2] = (float)absZ / _tabletZScale;
	instrumentState->floats()[3] = (float)pressure / _tabletPScale;
	instrumentState->floats()[4] = (float)tilt.x / _tabletTiltXScale;
	instrumentState->floats()[5] = (float)tilt.y / _tabletTiltYScale;
	instrument->setState(*instrumentState);
}

- (void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize {
	[self setFrame:[[self superview] bounds]];
	[self needsDisplay];
}

- (void)keyDown:(NSEvent *)theEvent {
	if ([theEvent keyCode] == 53){
		if ([self isInFullScreenMode]) {
			[self exitFullScreenModeWithOptions:nil];
		}
	}
}


@end
